Saltar al contenido principal

5.2 Argumentos Arbitrarios

En muchas situaciones no se conoce de antemano cuántos valores recibirá una función.
Para estos casos, Python permite definir funciones que acepten un número variable de argumentos, tanto posicionales como con nombre.
Esto se logra mediante los operadores * y **, conocidos respectivamente como *args y **kwargs.

Gracias a ellos, una función puede adaptarse a diferentes contextos sin necesidad de definir cada parámetro de forma explícita.


1️⃣ Argumentos posicionales arbitrarios (*args)​

Cuando se antepone un asterisco * a un parámetro, Python agrupa todos los argumentos posicionales recibidos en una tupla.
Esto permite que la función acepte una cantidad indefinida de valores.

Sintaxis general​

✍️ Definición de una función con *args
def sumar_todo(*numeros):
"""Suma todos los valores pasados como argumentos."""
total = 0
for n in numeros:
total += n
return total

print(sumar_todo(3, 5, 9))
print(sumar_todo(10, 20, 30, 40))
en este ejemplo

El parámetro *numeros recoge todos los argumentos que se pasen al llamar la función. Estos se almacenan en una tupla.

  • En el primer ejemplo, numeros = (3, 5, 9) y el resultado será la suma de esos tres valores (17).
  • En el segundo, numeros = (10, 20, 30, 40) y el resultado es 100.

Ejemplo práctico: concatenar cadenas​

Uso de *args para concatenar cadenas
def concatenar(*palabras):
"""Une todas las palabras en una sola cadena separada por espacios."""
resultado = " ".join(palabras)
return resultado

print(concatenar("Hola", "mundo"))
print(concatenar("Python", "es", "genial"))
Uso combinado con parámetros fijos

Una función puede tener parámetros fijos y además un conjunto de argumentos arbitrarios. Los parámetros definidos al principio se asignan primero, y los restantes se agrupan en la tupla *args.

Combinación de parámetros fijos y *args
def mostrar_info(nombre, *hobbies):
"""Muestra el nombre y la lista de aficiones de una persona."""
print(f"Nombre: {nombre}")
for h in hobbies:
print(f" - {h}")

mostrar_info("Laura", "leer", "correr", "viajar")
en este ejemplo
  • El primer argumento ("Laura") se asigna al parámetro fijo nombre.
  • Los demás ("leer", "correr", "viajar") se agrupan en la tupla hobbies.
  • La función recorre esa tupla con un bucle for y muestra cada afición.

2️⃣ Argumentos con nombre arbitrarios (**kwargs)​

Cuando se anteponen dos asteriscos ** a un parámetro, Python agrupa todos los argumentos con nombre en un diccionario. Cada par clave-valor representa el nombre del argumento y su valor asociado.

Sintaxis general​

✍️ Definición de una función con **kwargs
def mostrar_datos(**info):
"""Muestra los pares clave:valor recibidos."""
for clave, valor in info.items():
print(f"{clave}: {valor}")

mostrar_datos(nombre="Ana", edad=25, ciudad="Madrid")
en este ejemplo
  • Todos los argumentos con nombre (nombre, edad, ciudad) se almacenan dentro del diccionario info.
  • Por tanto, info = {'nombre': 'Ana', 'edad': 25, 'ciudad': 'Madrid'}.
  • El método .items() permite recorrer las claves y sus valores para mostrarlos uno a uno.

Ejemplo práctico​

Uso de **kwargs para formatear texto
def perfil_usuario(**datos):
"""Devuelve una descripción a partir de la información del usuario."""
nombre = datos["nombre"]
edad = datos["edad"]
ciudad = datos.get("ciudad", "Ciudad no especificada")
return f"{nombre} ({edad} años) - {ciudad}"

print(perfil_usuario(nombre="Carlos", edad=30))
print(perfil_usuario(nombre="Lucía", edad=22, ciudad="Sevilla"))
en este ejemplo

La función perfil_usuario() toma cualquier conjunto de datos con nombre.

Usa las claves nombre y edad, y accede a ciudad con .get() para ofrecer un valor alternativo si no existe.

De esta manera se genera una descripción flexible del usuario.


3️⃣ Combinación de *args y **kwargs​

Ambos mecanismos pueden combinarse en una misma función. Esto permite recibir simultáneamente argumentos posicionales arbitrarios y con nombre.

Ejemplo general​

Combinación de *args y **kwargs
def resumen(*args, **kwargs):
"""Muestra todos los argumentos recibidos, tanto posicionales como con nombre."""
print("Argumentos posicionales:", args)
print("Argumentos con nombre:", kwargs)

resumen(10, 20, 30, nombre="Ana", edad=25)
en este ejemplo

args almacena los valores posicionales en una tupla: (10, 20, 30). kwargs almacena los pares con nombre en un diccionario: {'nombre': 'Ana', 'edad': 25}. Esta técnica hace que la función sea muy flexible.

Orden correcto de los parámetros

El orden de los distintos tipos de parámetros en una definición debe seguir una secuencia específica.

Orden recomendado de parámetros
def ejemplo(a, b, *args, clave1, clave2="X", **kwargs):
pass
  1. Parámetros posicionales normales (a, b)
  2. Argumentos posicionales arbitrarios (*args)
  3. Parámetros con nombre obligatorios (clave1)
  4. Parámetros con nombre con valor por defecto (clave2="X")
  5. Argumentos con nombre arbitrarios (**kwargs)

Este orden evita errores en la asignación de argumentos durante la llamada.

Ejemplo práctico​

Función con todo tipo de parámetros
def registrar_evento(usuario, *acciones, nivel="INFO", **detalles):
"""Registra información sobre una acción realizada por un usuario."""
print(f"Usuario: {usuario}")
print(f"Nivel: {nivel}")
print("Acciones:")
for accion in acciones:
print(f" - {accion}")
print("Detalles adicionales:")
for clave, valor in detalles.items():
print(f" {clave}: {valor}")

registrar_evento("admin", "login", "borrar_datos", nivel="ALERTA", ip="192.168.1.2", hora="12:45")
en este ejemplo

Esta función combina todos los tipos de argumentos posibles:

  • usuario es un parámetro fijo.
  • *acciones agrupa las operaciones realizadas por el usuario.
  • nivel tiene un valor por defecto.
  • **detalles almacena la información adicional, como la IP o la hora.

El resultado muestra toda la información de manera ordenada.


4️⃣ Desempaquetado de colecciones​

Python permite utilizar los operadores * y ** también al llamar a una función. En este caso, sirven para desempaquetar una lista, tupla o diccionario y pasar sus elementos como argumentos individuales.

🟩 Desempaquetado de listas o tuplas​

Desempaquetado con * en la llamada
def multiplicar(a, b, c):
"""Multiplica tres valores."""
return a * b * c

valores = (2, 3, 4)
print(multiplicar(*valores)) # 24
en este ejemplo
  • El operador * en la llamada expande la tupla (2, 3, 4) en tres argumentos posicionales.
  • La función recibe los valores como si se hubiera escrito directamente multiplicar(2, 3, 4).

🟦 Desempaquetado de diccionarios​

Desempaquetado con ** en la llamada
def mostrar_persona(nombre, edad, ciudad):
"""Muestra los datos de una persona."""
print(f"{nombre} ({edad}) - {ciudad}")

datos = {"nombre": "Laura", "edad": 29, "ciudad": "Madrid"}
mostrar_persona(**datos)
en este ejemplo
  • El operador ** desempaqueta el diccionario datos y pasa cada par clave:valor como argumento con nombre.
  • Esto equivale exactamente a escribir mostrar_persona(nombre="Laura", edad=29, ciudad="Madrid").

5️⃣ Aplicaciones prácticas​

🟩 Procesamiento de operaciones variables​

Ejemplo de *args para cálculos
def producto_total(*numeros):
"""Calcula el producto de todos los números proporcionados."""
resultado = 1
for n in numeros:
resultado *= n
return resultado

print(producto_total(2, 3))
print(producto_total(1, 2, 3, 4, 5))
en este ejemplo

El parámetro *numeros permite multiplicar cualquier cantidad de valores. En la primera llamada se calculan 2 * 3 = 6, y en la segunda 1 * 2 * 3 * 4 * 5 = 120.

🟦 Construcción dinámica de mensajes​

Ejemplo de construcción de mensajes con **kwargs
def construir_mensaje(**partes):
"""Construye un mensaje a partir de pares clave:valor."""
mensaje = []
for clave, valor in partes.items():
mensaje.append(f"{clave.upper()}: {valor}")
return " | ".join(mensaje)

print(construir_mensaje(usuario="admin", estado="activo", rol="supervisor"))
en este ejemplo

Cada par clave:valor se convierte en texto, y luego se unen todos con " | ". Es útil para generar cadenas dinámicas y bien formateadas.

📊 Tabla resumen​

Tipo de argumentoSímboloTipo de datos que recibeForma de accesoEjemplo
Posicional arbitrario*argsTupla de valoresIteración directafor n in args:
Con nombre arbitrario**kwargsDiccionario clave:valor.items()for k,v in kwargs.items():

Los argumentos arbitrarios (*args, **kwargs) permiten crear funciones más versátiles y adaptables, capaces de recibir cualquier número y tipo de parámetros sin perder legibilidad ni control.